import NavBar from '@/components/NavBar'
import { DatePicker, Dialog, List, Popup, Toast } from 'antd-mobile'
import styles from './index.module.scss'

import { useDispatch, useSelector } from 'react-redux'
import { useEffect, useRef, useState } from 'react'
import {
  clearTokenAPI,
  editUserPtotoAPI,
  getProfileAPI,
  updateProfileAPI,
} from '@/store/action/user'
import { RootState } from '@/store'

import { Profile } from '@/store/reducer/user'
import Input from '@/components/Input'
import Textarea from '@/components/Textarea'
import dayjs from 'dayjs'
import { removeTokenInfo } from '@/utils/storage'
import history from '@/utils/history'

// 定义底部弹出层类型，TS修改代码的时候有更好的提示和静态校验
type PopupBottom = {
  visible: boolean
  // string 类型范围太大，把类型收窄为 'photo' | 'gender' | ''
  type: 'photo' | 'gender' | ''
}

// 定义右侧弹出层类型，TS修改代码的时候有更好的提示和静态校验
type PopupRight = {
  visible: boolean
  // string 类型范围太大，把类型收窄为 'name' | 'intro' | ''
  type: 'name' | 'intro' | ''
}

export default function ProfileEdit() {
  const dispatch = useDispatch()
  // 组件挂载时
  useEffect(() => {
    dispatch(getProfileAPI())
  }, [dispatch])

  // 获取到Redux个人资料数据渲染页面
  const { profile } = useSelector((state: RootState) => state.user)

  // 底部弹出显示状态
  const [popupBottom, setPopupBottom] = useState<PopupBottom>({
    visible: false,
    type: '',
  })

  // 右侧弹出显示状态
  const [popupRight, setPopupRight] = useState<PopupRight>({
    visible: false,
    type: '',
  })

  // 关闭弹出层的封装 , 方便使用
  const popupClose = () => {
    // 关闭底部
    setPopupBottom({ visible: false, type: '' })
    // 关闭右侧
    setPopupRight({ visible: false, type: '' })
  }

  // 获取到 input
  const fileRef = useRef<HTMLInputElement>(null)
  // 文件发生变化时触发
  const dandelFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      const file = e.target.files[0]
      // 上传文件需要 FormData
      const formDate = new FormData()
      // 追加参数
      formDate.append('photo', file)
      // 调用 action
      dispatch(editUserPtotoAPI(formDate))
      // 提示用户
      Toast.show({ content: '上传成功' })
      // 关闭弹窗
      popupClose()
    }
  }

  // 封装修改用户资料事件处理函数  改性别，改昵称，改生日，改简介
  const handelUpdateProfile = (data: Partial<Profile>) => {
    // 调用 action
    dispatch(updateProfileAPI(data))
    // 提示用户
    Toast.show({ content: '修改成功' })
    // 关闭弹窗
    popupClose()
  }

  // 昵称数据
  const [name, setName] = useState('')

  // 简介数据
  const [intro, setIntro] = useState('')

  // 封装右侧弹出层
  const popupRightOpen = (type: 'name' | 'intro') => {
    // 设置表单默认值
    if (type === 'name') {
      setName(profile.name)
    }
    if (type === 'intro') {
      setIntro(profile.intro)
    }
    // 打开右侧弹出层
    setPopupRight({ visible: true, type: type })
  }

  // 点击提交触发事件
  const handleSubmit = () => {
    // 调用封装函数 修改昵称和简介
    if (popupRight.type === 'name') {
      handelUpdateProfile({ name })
    } else if (popupRight.type === 'intro') {
      handelUpdateProfile({ intro })
    }
  }
  // 点击回车修改昵称
  const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      handleSubmit()
    }
  }

  // 定义日期选择器显示数据
  const [dateShow, setDateShow] = useState(false)

  //选择日期确认函数
  const handleConfirm = (value: Date) => {
    // 处理日期格式
    const birthday = dayjs(value).format('YYYY-MM-DD')
    // 调用封装函数修改数据
    handelUpdateProfile({ birthday })
  }

  // 退出登录
  const handleLogout = () => {
    Dialog.confirm({
      title: '温馨提示',
      content: '是否真的要走?',
      confirmText: '拜拜了您呐',
      cancelText: '留下来',
      onConfirm: () => {
        // 清除本地 Token
        removeTokenInfo()
        // 清除 Rudux Token
        dispatch(clearTokenAPI())
        // 提示用户
        Toast.show({ content: '退出成功' })
        // 跳转页面
        history.push('/login')
      },
    })
  }

  return (
    <div className={styles.root}>
      <div className="content">
        {/* 顶部导航栏 */}
        <NavBar>个人资料</NavBar>
        <div className="wrapper">
          {/* 列表一：显示头像、昵称、简介 */}
          <List className="profile-list">
            <List.Item
              arrow
              extra={<img className="avatar" src={profile.photo} alt="" />}
              onClick={() => setPopupBottom({ visible: true, type: 'photo' })}
            >
              头像
            </List.Item>

            <List.Item
              arrow
              extra={profile.name}
              onClick={() => popupRightOpen('name')}
            >
              昵称
            </List.Item>

            <List.Item
              arrow
              extra={profile.intro ?? <span className="intro">{'未填写'}</span>}
              onClick={() => popupRightOpen('intro')}
            >
              简介
            </List.Item>

            <List.Item
              arrow
              extra={profile.gender === 0 ? '男' : '女'}
              onClick={() => setPopupBottom({ visible: true, type: 'gender' })}
            >
              性别
            </List.Item>
            <List.Item
              arrow
              extra={profile.birthday}
              onClick={() => setDateShow(true)}
            >
              生日
            </List.Item>
          </List>

          {/* 文件选择框，用于头像图片的上传 */}
          <input
            ref={fileRef}
            className="avatar-upload"
            type="file"
            onChange={(e) => dandelFileChange(e)}
            accept=".png,.jpg"
          />
        </div>

        {/* 底部栏：退出登录按钮 */}
        <div className="logout">
          <button className="btn" onClick={handleLogout}>
            退出登录
          </button>
        </div>

        {/* 底部弹出层 */}
        <Popup
          visible={popupBottom.visible}
          position="bottom"
          bodyClassName="popup-bottom-list"
          onMaskClick={() => popupClose()}
        >
          {/* 复用弹出层 */}
          {popupBottom.type === 'photo' ? (
            <>
              <div
                className="list-item"
                onClick={() => fileRef.current?.click()}
              >
                拍照
              </div>
              <div
                className="list-item"
                onClick={() => fileRef.current?.click()}
              >
                本地选择
              </div>
            </>
          ) : (
            <>
              <div
                className="list-item"
                onClick={() => handelUpdateProfile({ gender: 0 })}
              >
                男
              </div>
              <div
                className="list-item"
                onClick={() => handelUpdateProfile({ gender: 1 })}
              >
                女
              </div>
            </>
          )}

          <div className="list-item" onClick={() => popupClose()}>
            取消
          </div>
        </Popup>

        {/* 右侧弹出层 */}
        <Popup
          visible={popupRight.visible}
          position="right"
          bodyClassName="popup-right"
          // 不可见时卸载内容, 用于配合表单加载时获取焦点
          destroyOnClose
        >
          <NavBar
            onBack={() => popupClose()}
            right={<span onClick={handleSubmit}>提交</span>}
          >
            编辑用户信息
          </NavBar>
          {popupRight.type === 'name' ? (
            <div className="edit-content">
              <h3 className="edit-title">编辑昵称</h3>
              {/* utoFocus 自动获取焦点 */}
              <Input
                className="edit-input"
                autoFocus
                onKeyUp={(e) => handleKeyUp(e)}
                // 受控组件
                value={name}
                onChange={(e) => setName(e.target.value)}
              />
            </div>
          ) : (
            <>
              <h3 className="edit-title">编辑简介</h3>
              <Textarea
                autoFocus
                placeholder="请输入个人简介"
                maxLength={10}
                value={intro}
                onChange={(e) => setIntro(e.target.value)}
              />
            </>
          )}
        </Popup>

        {/* 日期选择器 */}
        <DatePicker
          visible={dateShow}
          min={new Date('1940-01-01')}
          max={new Date()}
          onClose={() => setDateShow(false)}
          onConfirm={(e) => handleConfirm(e)}
          value={new Date(profile.birthday)}
        />
      </div>
    </div>
  )
}
